<!DOCTYPE html>
<html lang = "en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width-device width,user scalable-no,initial scale=1.0,maximum-scale=l.0,minimum scale=l.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Title</title>

    <script src="js/jquery.min.js"></script>
    <script>
        //关于异步的一些es6的写法 promise  generator,yield  async,await
        //==================================================
        //promise,通过同步的写法来实现异步操作
        //模拟有2个需要读取的api
        //第一个
        let promise1 = new Promise(function (resolve, reject) {
            //promise需要传入2个参数,resolve:成功后,reject:失败后

            //使用ajax来模拟异步操作(需要额外载入jquery)
            $.ajax({
                //随便测试在线api
                url: 'http://192.168.1.90:28080/arrTest.txt', //nas的nginx,需要额外开启跨域支持
                dataType: 'json',
                success(msg){
                    resolve(msg);
                },
                error(err){
                    //alert('failed')   //原来的写法,现在可以用reject来替换
                    reject(err);
                }
            })
        });

        //第二个
        let promise2 = new Promise(function (resolve, reject) {
            $.ajax({
                url: 'http://192.168.1.90:28080/jsonTest.txt',
                dataType: 'json',
                success(msg){resolve(msg);},
                error(err){reject(err);}
            })
        });

        //之后的操作,参数1:成功后,参数2:失败后
        promise1.then(
            function (msg) {
                alert('load file succeed!  '+msg);  //1,2,3,4,5 如果写入的时json数据则返回obj
            },
            function (err) {
                console.log(err);   //可以通过这里查看错误的对象
                alert('load file failed...');
            }
        );

        //如果有很多个promise再用promise2.then,promise2.then...就和原来ajax的写法一样,比较笨重
        //此处可以采用Promise.all来全部接受(通过数组),采用的是and,必须全部成功才会调用resolve
        Promise.all([
            promise1,promise2
        ]).then(
            function (res) {
                alert('all succeed!');
                let [res1,res2] = res;  //使用了解构赋值
                alert(res1);
                alert(JSON.stringify(res2));
            },
            function () {
                alert("at least one failed")
            }
        );

        //但是上面写法还是很蠢,改进后
        //先创建个一个可复用的ajax方法
        function createPromise(url) {
            //直接将结果返回
            return new Promise(function (resolve, reject) {
                $.ajax({
                    url,    //常规写法url: url,当2个url相同时可以简写
                    dataType: 'json',
                    success(msg){resolve(msg);},
                    error(err){reject(err);}
                })
            })
        }

        //直接套用createPromise
        Promise.all([
                createPromise('http://192.168.1.90:28080/arrTest.txt'),
                createPromise('http://192.168.1.90:28080/jsonTest.txt')
            ]).then(
                function (res) {
                    alert('all succeed!');
                    let [res1,res2] = res;
                    alert(res1);
                    alert(JSON.stringify(res2));
                },
                function () {
                    alert("at least one failed")
                }
        );

        //实际上ajax返回值就是promise对象(高版本的jq)
        let ajax = $.ajax({url: 'http://192.168.1.90:28080/arrTest.txt',dataType: 'json'});
        console.log(ajax);
        /*
        {readyState: 1, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}
        readyState: 4
        getResponseHeader: ƒ (e)
        getAllResponseHeaders: ƒ ()
        setRequestHeader: ƒ (e,t)
        overrideMimeType: ƒ (e)
        statusCode: ƒ (e)
        abort: ƒ (e)
        state: ƒ ()
        always: ƒ ()
        catch: ƒ (e)
        pipe: ƒ ()
        then: ƒ (t,n,r)
        promise: ƒ (e)
        progress: ƒ ()
        done: ƒ ()
        fail: ƒ ()
        responseText: "[1,2,3,4,5]"
        responseJSON: (5) [1, 2, 3, 4, 5]
        status: 200
        statusText: "OK"
        __proto__: Object
        */

        //因此也可以这么写
        Promise.all([
            $.ajax({url: 'http://192.168.1.90:28080/arrTest.txt',dataType: 'json'}),
            $.ajax({url: 'http://192.168.1.90:28080/jsonTest.txt',dataType: 'json'})
        ]).then(
            function (res) {
                alert('all succeed!');
                let [res1,res2] = res;
                console.log(res1,res2)
            },
            function () {
                alert("at least one failed")
            }
        );

        //通过箭头函数来表示
        Promise.all([
            $.ajax({url: 'http://192.168.1.90:28080/arrTest.txt',dataType: 'json'}),
            $.ajax({url: 'http://192.168.1.90:28080/jsonTest.txt',dataType: 'json'})
        ]).then(
            result => {
                alert('all succeed!');
                let [res1,res2] = result;
                console.log(res1,res2)
            },
            err=> {
                alert("at least one failed");
                console.log(err);
            }
        );


        //除了Promise.all以外,还有.race,读取多个资源优先返回第一个读取成功的数据,因此只会返回一个结果   演示略


        //==================================================
        // generator,yield 和 async,await
        // 当遇到promise无法处理的情况,例如判断a返回的值再去异步获取b,再判断b的结果再去获取c...
        // 此时需要使用generator和yield来处理使代码简洁
        function *test () {  //通过*funcName来标识这是generator
            alert('a');
            let res1 = yield;   //第一次next只会执行等号右边的yield!
            alert(res1);        //1
        }

        let doTest = test();    //调用generator函数
        // 当遇到yield时会放弃执行下一步,需要当外部执行next时才会继续执行
        doTest.next(0);       //执行*test()中,第一行到第一个yield的代码;注意,此时传入n的参数无法执行,如果需要预处理只能在test()中传入参数
        let res = doTest.next(1);     //将param传入执行第一个yield(即赋值给res1)
        console.log(res);       //next是有返回值的,obj{value: undefined,done: true},done表示是否已经到底


        //在实际异步调用时候的应用 (需要借助另外的库,实际操作略)
        /*
        runner(function *(){
            let res1 = yield $.ajax({url: 'http://192.168.1.90:28080/arrTest.txt',dataType: 'json'});
            let res2 = yield $.ajax({url: 'http://192.168.1.90:28080/arrTest.txt',dataType: 'json'});
            ...
            console.log(res1,res2...);
            //通过同步的写法来实现异步的操作
        });
        */


        //但之后又开发了Async和Await基本完全可以替代generator和yield,async和await可以看作是g和y的语法糖,底层作用的还是gy
        async function show(){  //实际async的用途是标识,让可以暂停;普通的函数不可以暂停
            console.log('start...');
            //进行等待(异步)操作

            //可以用try catch来捕获await (本质返回的结果是promise对象)中的错误
            try{
                let res = await $.ajax({url: 'http://192.168.1.90:28080/arrTest.txt',dataType: 'json'});
                alert(res);
            }catch (e) {
                alert('failed!');
                console.log('show() failed: ',e)
            }
            //关于try catch,因为JavaScript频繁需要采用异步,无法通过try catch来捕获而是通过回调来显示错误,使用promise后可以很方便的使用try catch来进行抓错

            //补充:async实际会将函数进行拆分,await之前为一个函数,await单独一个,在执行await中的ajax时与promise一样会.then,在成功处再执行await之后的代码
        }

        let res2 = show();
        console.log(res2)    //返回的结果为promise对象

        //promise与async+await的区别
        //promise为异步操作提供了封装
        //async+await则更加灵活

    </script>
</head>


<body>
<script type="text/javascript">

</script>



</body>
</html>



